package com.flexrrb.managers
{
	import flash.display.DisplayObject;
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	import flash.utils.getQualifiedClassName;

	import mx.containers.Canvas;
	import mx.containers.Panel;
	import mx.controls.Button;
	import mx.core.Container;
	import mx.core.UIComponent;
	import mx.core.UITextField;
	import mx.core.mx_internal;
	import mx.managers.CursorManager;
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.StyleManager;
	use namespace mx_internal;

	[Event(name="minimize", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="restore", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="maximize", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="close", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="focusStart", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="focusEnd", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="dragStart", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="drag", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="dragEnd", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="resizeStart", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="resize", type="flexlib.mdi.events.MDIWindowEvent")]

	[Event(name="resizeEnd", type="flexlib.mdi.events.MDIWindowEvent")]

	[Style(name="styleNameFocus", type="String", inherit="no")]

	[Style(name="styleNameNoFocus", type="String", inherit="no")]

	[Style(name="titleStyleNameFocus", type="String", inherit="no")]

	[Style(name="titleStyleNameNoFocus", type="String", inherit="no")]

	[Style(name="windowControlsClass", type="Class", inherit="no")]

	[Style(name="minimizeBtnStyleName", type="String", inherit="no")]

	[Style(name="minimizeBtnStyleNameNoFocus", type="String", inherit="no")]

	[Style(name="maximizeBtnStyleName", type="String", inherit="no")]

	[Style(name="maximizeBtnStyleNameNoFocus", type="String", inherit="no")]

	[Style(name="restoreBtnStyleName", type="String", inherit="no")]

	[Style(name="restoreBtnStyleNameNoFocus", type="String", inherit="no")]

	[Style(name="closeBtnStyleName", type="String", inherit="no")]

	[Style(name="closeBtnStyleNameNoFocus", type="String", inherit="no")]

	[Style(name="resizeCursorHorizontalSkin", type="Class", inherit="no")]

	[Style(name="resizeCursorHorizontalXOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorHorizontalYOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorVerticalSkin", type="Class", inherit="no")]

	[Style(name="resizeCursorVerticalXOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorVerticalYOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorTopLeftBottomRightSkin", type="Class", inherit="no")]

	[Style(name="resizeCursorTopLeftBottomRightXOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorTopLeftBottomRightYOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorTopRightBottomLeftSkin", type="Class", inherit="no")]

	[Style(name="resizeCursorTopRightBottomLeftXOffset", type="Number", inherit="no")]

	[Style(name="resizeCursorTopRightBottomLeftYOffset", type="Number", inherit="no")]

	public class TransformationManager extends UIComponent
	{

		public var edgeHandleSize:Number=4;

		public var cornerHandleSize:Number=10;

		public var resizable:Boolean=true;

		public var draggable:Boolean=true;

		private var resizeHandleTop:Button;

		private var resizeHandleRight:Button;

		private var resizeHandleBottom:Button;

		private var resizeHandleLeft:Button;

		private var resizeHandleTL:Button;

		private var resizeHandleTR:Button;

		private var resizeHandleBR:Button;

		private var resizeHandleBL:Button;

		private var currentResizeHandle:Button;

		public var savedWindowRect:Rectangle;

		private var _resizing:Boolean;

		private var _dragging:Boolean;

		private var dragStartMouseX:Number;

		private var dragStartMouseY:Number;

		private var dragMaxX:Number;

		private var dragMaxY:Number;

		private var dragAmountX:Number;

		private var dragAmountY:Number;

		private var backgroundAlphaRestore:Number=1;

		protected var _target:UIComponent;

		[Embed(source="/assets/resizeCursorH.gif")]
		private static var resizeCursorHorizontalSkin:Class;
		private static var DEFAULT_RESIZE_CURSOR_HORIZONTAL_X_OFFSET:Number=-10;
		private static var DEFAULT_RESIZE_CURSOR_HORIZONTAL_Y_OFFSET:Number=-10;

		[Embed(source="/assets/resizeCursorV.gif")]
		private static var resizeCursorVerticalSkin:Class;
		private static var DEFAULT_RESIZE_CURSOR_VERTICAL_X_OFFSET:Number=-10;
		private static var DEFAULT_RESIZE_CURSOR_VERTICAL_Y_OFFSET:Number=-10;

		[Embed(source="/assets/resizeCursorTLBR.gif")]
		private static var resizeCursorTopLeftBottomRightSkin:Class;
		private static var DEFAULT_RESIZE_CURSOR_TL_BR_X_OFFSET:Number=-10;
		private static var DEFAULT_RESIZE_CURSOR_TL_BR_Y_OFFSET:Number=-10;

		[Embed(source="/assets/resizeCursorTRBL.gif")]
		private static var resizeCursorTopRightBottomLeftSkin:Class;
		private static var DEFAULT_RESIZE_CURSOR_TR_BL_X_OFFSET:Number=-10;
		private static var DEFAULT_RESIZE_CURSOR_TR_BL_Y_OFFSET:Number=-10;

		public function TransformationManager()
		{
			super();
		}

		public function get target():UIComponent
		{
			return _target;
		}

		public function set target(value:UIComponent):void
		{
			_target=value;
			createBorders();
		}

		private function createBorders():void
		{
			if (!resizeHandleTop)
			{
				resizeHandleTop=new Button();
				resizeHandleTop.x=cornerHandleSize * .5;
				resizeHandleTop.y=-(edgeHandleSize * .5);
				resizeHandleTop.height=edgeHandleSize;
				//resizeHandleTop.alpha=0;
				resizeHandleTop.focusEnabled=false;
				target.addChild(resizeHandleTop);
			}

			if (!resizeHandleRight)
			{
				resizeHandleRight=new Button();
				resizeHandleRight.y=cornerHandleSize * .5;
				resizeHandleRight.width=edgeHandleSize;
				//resizeHandleRight.alpha=0;
				resizeHandleRight.focusEnabled=false;
				target.addChild(resizeHandleRight);
			}

			if (!resizeHandleBottom)
			{
				resizeHandleBottom=new Button();
				resizeHandleBottom.x=cornerHandleSize * .5;
				resizeHandleBottom.height=edgeHandleSize;
				//resizeHandleBottom.alpha=0;
				resizeHandleBottom.focusEnabled=false;
				target.addChild(resizeHandleBottom);
			}

			if (!resizeHandleLeft)
			{
				resizeHandleLeft=new Button();
				resizeHandleLeft.x=-(edgeHandleSize * .5);
				resizeHandleLeft.y=cornerHandleSize * .5;
				resizeHandleLeft.width=edgeHandleSize;
				//resizeHandleLeft.alpha=0;
				resizeHandleLeft.focusEnabled=false;
				target.addChild(resizeHandleLeft);
			}

			if (!resizeHandleTL)
			{
				resizeHandleTL=new Button();
				resizeHandleTL.x=resizeHandleTL.y=-(cornerHandleSize * .3);
				resizeHandleTL.width=resizeHandleTL.height=cornerHandleSize;
				//resizeHandleTL.alpha=0;
				resizeHandleTL.focusEnabled=false;
				target.addChild(resizeHandleTL);
			}

			if (!resizeHandleTR)
			{
				resizeHandleTR=new Button();
				resizeHandleTR.width=resizeHandleTR.height=cornerHandleSize;
				//resizeHandleTR.alpha=0;
				resizeHandleTR.focusEnabled=false;
				target.addChild(resizeHandleTR);
			}

			if (!resizeHandleBR)
			{
				resizeHandleBR=new Button();
				resizeHandleBR.width=resizeHandleBR.height=cornerHandleSize;
				//resizeHandleBR.alpha=0;
				resizeHandleBR.focusEnabled=false;
				target.addChild(resizeHandleBR);
			}

			if (!resizeHandleBL)
			{
				resizeHandleBL=new Button();
				resizeHandleBL.width=resizeHandleBL.height=cornerHandleSize;
				//resizeHandleBL.alpha=0;
				resizeHandleBL.focusEnabled=false;
				target.addChild(resizeHandleBL);
			}

			addListeners();
		}


		override protected function createChildren():void
		{
			super.createChildren();
		}

		override protected function updateDisplayList(w:Number, h:Number):void
		{
			super.updateDisplayList(w, h);
			if(target){
			resizeHandleTop.x=cornerHandleSize * .5;
			resizeHandleTop.y=-(edgeHandleSize * .5);
			resizeHandleTop.width=this.width - cornerHandleSize;
			resizeHandleTop.height=edgeHandleSize;

			resizeHandleRight.x=this.width - edgeHandleSize * .5;
			resizeHandleRight.y=cornerHandleSize * .5;
			resizeHandleRight.width=edgeHandleSize;
			resizeHandleRight.height=this.height - cornerHandleSize;

			resizeHandleBottom.x=cornerHandleSize * .5;
			resizeHandleBottom.y=this.height - edgeHandleSize * .5;
			resizeHandleBottom.width=this.width - cornerHandleSize;
			resizeHandleBottom.height=edgeHandleSize;

			resizeHandleLeft.x=-(edgeHandleSize * .5);
			resizeHandleLeft.y=cornerHandleSize * .5;
			resizeHandleLeft.width=edgeHandleSize;
			resizeHandleLeft.height=this.height - cornerHandleSize;

			resizeHandleTL.x=resizeHandleTL.y=-(cornerHandleSize * .5);
			resizeHandleTL.width=resizeHandleTL.height=cornerHandleSize;

			resizeHandleTR.x=this.width - cornerHandleSize * .5;
			resizeHandleTR.y=-(cornerHandleSize * .5);
			resizeHandleTR.width=resizeHandleTR.height=cornerHandleSize;

			resizeHandleBR.x=this.width - cornerHandleSize * .5;
			resizeHandleBR.y=this.height - cornerHandleSize * .5;
			resizeHandleBR.width=resizeHandleBR.height=cornerHandleSize;

			resizeHandleBL.x=-(cornerHandleSize * .5);
			resizeHandleBL.y=this.height - cornerHandleSize * .5;
			resizeHandleBL.width=resizeHandleBL.height=cornerHandleSize;
			}
		}

		private function addListeners():void
		{
			resizeHandleTop.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleTop.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleTop.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleRight.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleRight.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleRight.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleBottom.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleBottom.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleBottom.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleLeft.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleLeft.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleLeft.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleTL.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleTL.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleTL.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleTR.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleTR.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleTR.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleBR.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleBR.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleBR.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

			resizeHandleBL.addEventListener(MouseEvent.ROLL_OVER, onResizeButtonRollOver, false, 0, true);
			resizeHandleBL.addEventListener(MouseEvent.ROLL_OUT, onResizeButtonRollOut, false, 0, true);
			resizeHandleBL.addEventListener(MouseEvent.MOUSE_DOWN, onResizeButtonPress, false, 0, true);

		}

		private function savePanel():void
		{
			savedWindowRect=new Rectangle(this.x, this.y, this.width, this.height);
		}

		private function onResizeButtonPress(event:MouseEvent):void
		{
			if (resizable)
			{
				currentResizeHandle=event.target as Button;
				setCursor(currentResizeHandle);
				dragStartMouseX=parent.mouseX;
				dragStartMouseY=parent.mouseY;
				savePanel();

				dragMaxX=savedWindowRect.x + (savedWindowRect.width - minWidth);
				dragMaxY=savedWindowRect.y + (savedWindowRect.height - minHeight);

				systemManager.addEventListener(Event.ENTER_FRAME, updateWindowSize, false, 0, true);
				systemManager.addEventListener(MouseEvent.MOUSE_MOVE, onResizeButtonDrag, false, 0, true);
				systemManager.addEventListener(MouseEvent.MOUSE_UP, onResizeButtonRelease, false, 0, true);
				systemManager.stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeaveStage, false, 0, true);
			}
		}

		private function onResizeButtonDrag(event:MouseEvent):void
		{
			if (!_resizing)
			{
				_resizing=true;
					//dispatchEvent(new MDIWindowEvent(MDIWindowEvent.RESIZE_START, this));
			}
			//dispatchEvent(new MDIWindowEvent(MDIWindowEvent.RESIZE, this));
		}

		private function updateWindowSize(event:Event):void
		{
			if (resizable)
			{
				dragAmountX=parent.mouseX - dragStartMouseX;
				dragAmountY=parent.mouseY - dragStartMouseY;

				if (currentResizeHandle == resizeHandleTop && parent.mouseY > 0)
				{
					this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
					this.height=Math.max(savedWindowRect.height - dragAmountY, minHeight);
				}
				else if (currentResizeHandle == resizeHandleRight && parent.mouseX < parent.width)
				{
					this.width=Math.max(savedWindowRect.width + dragAmountX, minWidth);
				}
				else if (currentResizeHandle == resizeHandleBottom && parent.mouseY < parent.height)
				{
					this.height=Math.max(savedWindowRect.height + dragAmountY, minHeight);
				}
				else if (currentResizeHandle == resizeHandleLeft && parent.mouseX > 0)
				{
					this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
					this.width=Math.max(savedWindowRect.width - dragAmountX, minWidth);
				}
				else if (currentResizeHandle == resizeHandleTL && parent.mouseX > 0 && parent.mouseY > 0)
				{
					this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
					this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
					this.width=Math.max(savedWindowRect.width - dragAmountX, minWidth);
					this.height=Math.max(savedWindowRect.height - dragAmountY, minHeight);
				}
				else if (currentResizeHandle == resizeHandleTR && parent.mouseX < parent.width && parent.mouseY > 0)
				{
					this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
					this.width=Math.max(savedWindowRect.width + dragAmountX, minWidth);
					this.height=Math.max(savedWindowRect.height - dragAmountY, minHeight);
				}
				else if (currentResizeHandle == resizeHandleBR && parent.mouseX < parent.width && parent.mouseY < parent.height)
				{
					this.width=Math.max(savedWindowRect.width + dragAmountX, minWidth);
					this.height=Math.max(savedWindowRect.height + dragAmountY, minHeight);
				}
				else if (currentResizeHandle == resizeHandleBL && parent.mouseX > 0 && parent.mouseY < parent.height)
				{
					this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
					this.width=Math.max(savedWindowRect.width - dragAmountX, minWidth);
					this.height=Math.max(savedWindowRect.height + dragAmountY, minHeight);
				}
			}
		}

		private function onResizeButtonRelease(event:MouseEvent=null):void
		{
			if (resizable)
			{
				if (_resizing)
				{
					_resizing=false;
						//dispatchEvent(new MDIWindowEvent(MDIWindowEvent.RESIZE_END, this));
				}
				currentResizeHandle=null;
				systemManager.removeEventListener(Event.ENTER_FRAME, updateWindowSize);
				systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, onResizeButtonDrag);
				systemManager.removeEventListener(MouseEvent.MOUSE_UP, onResizeButtonRelease);
				systemManager.stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeaveStage);
				CursorManager.removeCursor(CursorManager.currentCursorID);
			}
		}

		private function onMouseLeaveStage(event:Event):void
		{
			onResizeButtonRelease();
			systemManager.stage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeaveStage);
		}

		private function setCursor(target:Button):void
		{
			var styleStub:Class;

			switch (target)
			{
				case resizeHandleRight:
				case resizeHandleLeft:
					styleStub=resizeCursorHorizontalSkin;
					break;

				case resizeHandleTop:
				case resizeHandleBottom:
					styleStub=resizeCursorVerticalSkin;
					break;

				case resizeHandleTL:
				case resizeHandleBR:
					styleStub=resizeCursorTopLeftBottomRightSkin;
					break;

				case resizeHandleTR:
				case resizeHandleBL:
					styleStub=resizeCursorTopRightBottomLeftSkin;
					break;
			}

			CursorManager.removeCursor(CursorManager.currentCursorID);
			CursorManager.setCursor(styleStub, 2, -10, -10);
		}

		private function onResizeButtonRollOver(event:MouseEvent):void
		{
			if (resizable && !event.buttonDown)
			{
				setCursor(event.target as Button);
			}
		}

		private function onResizeButtonRollOut(event:MouseEvent):void
		{
			if (!event.buttonDown)
			{
				CursorManager.removeCursor(CursorManager.currentCursorID);
			}
		}
	}
}